package cn.elwy.rcp.ui.table;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.elwy.common.util.sort.SortUtil;
import cn.elwy.osgi.config.ConfigPath;
import cn.elwy.rcp.ui.table.adapter.TableConfigAdapter;
import cn.elwy.rcp.ui.table.internal.DefaultConfigFactory;
import cn.elwy.rcp.ui.table.model.ColumnInfo;
import cn.elwy.rcp.ui.table.model.TableConfig;
import cn.elwy.rcp.ui.table.model.TableInfo;

public class TableConfigFactory {

  private static Map<String, TableInfo> tableInfoMap = new HashMap<String, TableInfo>();
  public static final Map<String, TableInfo> tableInfoCacheMap = new HashMap<String, TableInfo>();
  public static final Map<String, TableConfig> tableConfigCacheMap = new HashMap<String, TableConfig>();

  // private static final Map<String, Boolean> tableConfigState = new HashMap<String, Boolean>();

  private TableConfigFactory() {
  }

  public static Map<String, TableInfo> getTableInfoMap() {
    return tableInfoMap;
  }

  public static void setTableInfoMap(String tableId, TableInfo tableInfo) {
    tableInfoMap.put(tableId, tableInfo);
  }

  // public static void setTableConfigState(String tableId, boolean state) {
  // tableConfigState.put(tableId, state);
  // }

  public static TableInfo getTableInfo(String tableId) {
    // 从缓存获取
    TableInfo tableInfo = tableInfoCacheMap.get(tableId);
    if (tableInfo != null) {
      return tableInfo;
    }
    // 从扩展点获取
    tableInfo = tableInfoMap.get(tableId);
    Object subjectId = getSubjectId(tableInfo);
    TableConfigAdapter tableConfigAdapter = tableInfo.getTableConfigAdapter();
    TableInfo temp = null;
    if (tableConfigAdapter != null) {
      // 使用自定义适配器获取
      temp = tableConfigAdapter.getTableInfo(subjectId, tableId);
    } else {
      temp = DefaultConfigFactory.getTableInfo(subjectId, tableId);
    }
    if (temp != null) {
      tableInfo = temp;
    } else {
      // 复制扩展点的配置
      tableInfo = newTableInfo(tableInfo);
    }
    TableConfig tableConfig = getTableConfig(subjectId, tableId, tableInfo);
    if (tableConfig != null) {
      mergeConfig(tableConfig, tableInfo);
    }
    SortUtil.sort(tableInfo.getColumnInfoList(), true, ColumnInfo.ORDER_FIELD);
    tableInfoCacheMap.put(tableId, tableInfo);
    return tableInfo;
  }

  public static void saveTableInfo(TableInfo tableInfo) {
    Object subjectId = getSubjectId(tableInfo);
    TableConfigAdapter tableConfigAdapter = tableInfo.getTableConfigAdapter();
    if (tableConfigAdapter != null) {
      tableConfigAdapter.saveTableInfo(subjectId, tableInfo);
    }
    DefaultConfigFactory.saveTableInfo(subjectId, tableInfo);
  }

  public static TableConfig getTableConfig(String tableId) {
    TableInfo tableInfo = getTableInfo(tableId);
    Object subjectId = getSubjectId(tableInfo);
    return getTableConfig(subjectId, tableId, tableInfo);
  }

  public static void saveTableConfig(TableInfo tableInfo) {
    TableConfigAdapter tableConfigAdapter = tableInfo.getTableConfigAdapter();
    TableConfig tableConfig = newTableConfig(tableInfo);
    for (ColumnInfo columnInfo : tableConfig.getColumnInfoList()) {
      columnInfo.setColumnFormat(null);
    }
    Object subjectId = getSubjectId(tableConfig);
    if (tableConfigAdapter != null) {
      tableConfigAdapter.saveTableConfig(subjectId, tableConfig);
    } else {
      DefaultConfigFactory.saveTableConfig(subjectId, tableConfig);
    }
  }

  public static TableInfo newTableInfo(TableInfo source) {
    TableInfo target = new TableInfo();
    target.setId(source.getId());
    target.setName(source.getName());
    // target.setStyle(source.getStyle());
    target.setStyleName(source.getStyleName());
    target.setType(source.getType());
    target.setHeaderVisible(source.isHeaderVisible());
    target.setLineVisible(source.isLineVisible());
    target.setLineHeight(source.getLineHeight());
    target.setMultipleSelection(source.isMultipleSelection());
    target.setAutoRefresh(source.isAutoRefresh());
    target.setDefaultRefreshInterval(source.getDefaultRefreshInterval());
    if (source.getColumnKeys() != null) {
      target.setColumnKeys(new ArrayList<String>(source.getColumnKeys()));
    }
    target.setColumnInfoList(newColumnInfoList(source));

    target.setCanCustomConfig(source.isCanCustomConfig());
    target.setCanSettingColumn(source.isCanSettingColumn());
    target.setCanEditor(source.isCanEditor());
    target.setCanSort(source.isCanSort());
    target.setCanSave(source.isCanSave());

    target.setButtonCompositeInfoList(source.getButtonCompositeInfoList());
    target.setContentProvider(source.getContentProvider());
    target.setLabelProvider(source.getLabelProvider());
    target.setViewerFilterList(source.getViewerFilterList());
    target.setActionGroup(source.getActionGroup());
    target.setActionList(source.getActionList());
    target.setCheckStateProvider(source.getCheckStateProvider());
    target.setCheckStateListener(source.getCheckStateListener());
    target.setDoubleClickListener(source.getDoubleClickListener());
    target.setDoubleClickListener(source.getDoubleClickListener());
    target.setDragSourceListener(source.getDragSourceListener());
    target.setDropTargetListener(source.getDropTargetListener());
    target.setKeyListener(source.getKeyListener());
    target.setMouseListener(source.getMouseListener());
    target.setPropertyChangedListener(source.getPropertyChangedListener());
    target.setSelectionChangedListener(source.getSelectionChangedListener());
    target.setTableEditorAdapter(source.getTableEditorAdapter());
    target.setTableConfigAdapter(source.getTableConfigAdapter());

    return target;
  }

  public static TableConfig newTableConfig(TableConfig source) {
    TableConfig target = new TableConfig();
    target.setId(source.getId());
    target.setName(source.getName());
    // target.setStyle(source.getStyle());
    target.setStyleName(source.getStyleName());
    target.setType(source.getType());
    target.setHeaderVisible(source.isHeaderVisible());
    target.setLineVisible(source.isLineVisible());
    target.setLineHeight(source.getLineHeight());
    target.setMultipleSelection(source.isMultipleSelection());
    target.setAutoRefresh(source.isAutoRefresh());
    target.setDefaultRefreshInterval(source.getDefaultRefreshInterval());

    if (source.getColumnKeys() != null) {
      target.setColumnKeys(new ArrayList<String>(source.getColumnKeys()));
    }
    target.setColumnInfoList(newColumnInfoList(source));

    target.setCanCustomConfig(source.isCanCustomConfig());
    target.setCanSettingColumn(source.isCanSettingColumn());
    target.setCanEditor(source.isCanEditor());
    target.setCanSort(source.isCanSort());
    target.setCanSave(source.isCanSave());
    return target;
  }

  public static TableConfig mergeConfig(TableConfig source, TableConfig target) {
    target.setId(source.getId());
    target.setName(source.getName());
    // target.setStyle(source.getStyle());
    target.setStyleName(source.getStyleName());
    target.setType(source.getType());
    target.setHeaderVisible(source.isHeaderVisible());
    target.setLineVisible(source.isLineVisible());
    target.setLineHeight(source.getLineHeight());
    target.setMultipleSelection(source.isMultipleSelection());
    target.setAutoRefresh(source.isAutoRefresh());
    target.setDefaultRefreshInterval(source.getDefaultRefreshInterval());

    target.setColumnKeys(source.getColumnKeys());
    target.setColumnInfoList(mergeColumnInfo(source, target));

    target.setCanCustomConfig(source.isCanCustomConfig());
    target.setCanSettingColumn(source.isCanSettingColumn());
    target.setCanEditor(source.isCanEditor());
    target.setCanSort(source.isCanSort());

    return target;
  }

  private static List<ColumnInfo> mergeColumnInfo(TableConfig source, TableConfig target) {
    List<ColumnInfo> columnInfoList = source.getColumnInfoList();
    List<ColumnInfo> resultList = target.getColumnInfoList();
    for (int i = 0; i < resultList.size(); i++) {
      ColumnInfo result = resultList.get(i);
      int index = columnInfoList.indexOf(result);
      ColumnInfo columnInfo = columnInfoList.get(index);

      result.setId(columnInfo.getId());
      result.setName(columnInfo.getName());
      // result.setStyle(columnInfo.getStyle());
      result.setStyleName(columnInfo.getStyleName());
      // result.setAlignment(columnInfo.getAlignment());
      result.setAlignmentName(columnInfo.getAlignmentName());
      result.setWidth(columnInfo.getWidth());
      if (columnInfo.getColumnFormat() != null) {
        result.setColumnFormat(columnInfo.getColumnFormat());
      }
      if (result.getColumnFormat() != null) {
        result.getColumnFormat().setPattern(columnInfo.getFormatPattern());
        result.setFormatPattern(columnInfo.getFormatPattern());
      }
      result.setOrder(columnInfo.getOrder());
      result.setVisible(columnInfo.isVisible());
      result.setCanVisible(columnInfo.isCanVisible());
      result.setCanEditor(columnInfo.isCanEditor());
    }
    return resultList;
  }

  private static List<ColumnInfo> newColumnInfoList(TableConfig source) {
    List<ColumnInfo> columnInfoList = source.getColumnInfoList();
    List<ColumnInfo> resultList = new ArrayList<ColumnInfo>();
    for (int i = 0; i < columnInfoList.size(); i++) {
      ColumnInfo result = new ColumnInfo();
      ColumnInfo columnInfo = columnInfoList.get(i);

      result.setId(columnInfo.getId());
      result.setName(columnInfo.getName());
      // result.setStyle(columnInfo.getStyle());
      result.setStyleName(columnInfo.getStyleName());
      // result.setAlignment(columnInfo.getAlignment());
      result.setAlignmentName(columnInfo.getAlignmentName());
      result.setWidth(columnInfo.getWidth());
      if (columnInfo.getColumnFormat() != null) {
        result.setColumnFormat(columnInfo.getColumnFormat());
      }
      if (result.getColumnFormat() != null) {
        result.getColumnFormat().setPattern(columnInfo.getFormatPattern());
        result.setFormatPattern(columnInfo.getFormatPattern());
      }
      result.setOrder(columnInfo.getOrder());
      result.setVisible(columnInfo.isVisible());
      result.setCanVisible(columnInfo.isCanVisible());
      result.setCanEditor(columnInfo.isCanEditor());
      resultList.add(result);
    }
    SortUtil.sort(resultList, true, ColumnInfo.ORDER_FIELD);
    return resultList;
  }

  private static TableConfig getTableConfig(Object subjectId, String tableId, TableInfo tableInfo) {
    String userTable = getCustomKey(subjectId, tableId);
    // 从缓存获取
    TableConfig tableConfig = tableConfigCacheMap.get(userTable);
    if (tableConfig != null) {
      return tableConfig;
    }
    TableConfigAdapter tableConfigAdapter = tableInfo.getTableConfigAdapter();
    if (tableConfigAdapter != null) {
      // 使用自定义适配器获取
      TableConfig temp = tableConfigAdapter.getTableConfig(subjectId, tableId);
      if (temp != null) {
        tableConfigCacheMap.put(userTable, temp);
        return temp;
      }
    }
    TableConfig temp = DefaultConfigFactory.getTableConfig(subjectId, tableId);
    if (temp != null) {
      tableConfigCacheMap.put(userTable, temp);
      return temp;
    }
    return tableConfig;
  }

  private static String getCustomKey(Object subjectId, String tableId) {
    if (subjectId == null) {
      return tableId;
    } else {
      return subjectId + "_" + tableId;
    }
  }

  public static Object getSubjectId(TableConfig tableConfig) {
    return ConfigPath.getSubjectId(tableConfig.isCanCustomConfig());
  }

}